home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / msdos / raytrace / pov / bin / xtras / quadrics.c < prev    next >
C/C++ Source or Header  |  1994-09-11  |  18KB  |  604 lines

  1. /****************************************************************************
  2. *
  3. *  ATTENTION!!!
  4. *
  5. *  THIS FILE HAS BEEN MODIFIED!!! IT IS NOT PART OF THE OFFICAL
  6. *  POV-RAY 2.2 DISTRIBUTION!!!
  7. *
  8. *  THIS FILE IS PART OF "FASTER THAN POV-RAY" (VERSION 2.2),
  9. *  A SPED-UP VERSION OF POV-RAY 2.2. USE AT YOUR OWN RISK!!!!!!
  10. *
  11. *  New files: addon0.c, addon1.c, addon2.c, addon3.c, addon.h
  12. *
  13. *  The additional modules were written by Dieter Bayer.
  14. *
  15. *  Send comments, suggestions, bugs, ideas ... to:
  16. *
  17. *  e-mail: dieter@cip.e-technik.uni-erlangen.de
  18. *  CIS: 100255.3074
  19. *
  20. *  All changed/added lines are enclosed in #ifdef DB_CODE ... #endif
  21. *
  22. *  The vista projection was taken from:
  23. *
  24. *    A. Hashimoto, T. Akimoto, K. Mase, and Y. Suenaga, 
  25. *    "Vista Ray-Tracing: High Speed Ray Tracing Using Perspective
  26. *    Projection Image", New Advances in Computer Graphics, Proceedings
  27. *    of CG International '89, R. A. Earnshaw, B. Wyvill (Eds.), 
  28. *    Springer, ..., pp. 549-560
  29. *
  30. *  The idea for the light buffer was taken from:
  31. *
  32. *    E. Haines and D. Greenberg, "The Light Buffer: A Shadow-Testing 
  33. *    Accelerator", IEEE CG&A, Vol. 6, No. 9, Sept. 1986, pp. 6-16
  34. *
  35. *****************************************************************************/
  36.  
  37. /****************************************************************************
  38. *                quadrics.c
  39. *
  40. *  This module implements the code for the quadric shape primitive.
  41. *
  42. *  from Persistence of Vision Raytracer
  43. *  Copyright 1993 Persistence of Vision Team
  44. *---------------------------------------------------------------------------
  45. *  NOTICE: This source code file is provided so that users may experiment
  46. *  with enhancements to POV-Ray and to port the software to platforms other 
  47. *  than those supported by the POV-Ray Team.  There are strict rules under
  48. *  which you are permitted to use this file.  The rules are in the file
  49. *  named POVLEGAL.DOC which should be distributed with this file. If 
  50. *  POVLEGAL.DOC is not available or for more info please contact the POV-Ray
  51. *  Team Coordinator by leaving a message in CompuServe's Graphics Developer's
  52. *  Forum.  The latest version of POV-Ray may be found there as well.
  53. *
  54. * This program is based on the popular DKB raytracer version 2.12.
  55. * DKBTrace was originally written by David K. Buck.
  56. * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
  57. *
  58. *****************************************************************************/
  59.  
  60. #include "frame.h"
  61. #include "vector.h"
  62. #include "povproto.h"
  63.  
  64. METHODS Quadric_Methods =
  65.   {
  66.   All_Quadric_Intersections,
  67.   Inside_Quadric, Quadric_Normal,
  68.   Copy_Quadric,
  69.   Translate_Quadric, Rotate_Quadric,
  70.   Scale_Quadric, Transform_Quadric, Invert_Quadric,
  71.   Destroy_Quadric
  72. };
  73.  
  74. extern RAY *CM_Ray;
  75. extern long Ray_Quadric_Tests, Ray_Quadric_Tests_Succeeded;
  76.  
  77. int All_Quadric_Intersections (Object, Ray, Depth_Stack)
  78. OBJECT *Object;
  79. RAY *Ray;
  80. ISTACK *Depth_Stack;
  81.   {
  82.   DBL Depth1, Depth2;
  83.   VECTOR IPoint;
  84.   register int Intersection_Found;
  85.  
  86.   Intersection_Found = FALSE;
  87.  
  88.   if (Intersect_Quadric (Ray, (QUADRIC *) Object, &Depth1, &Depth2))
  89.     {
  90.     VScale (IPoint, Ray->Direction, Depth1);
  91.     VAddEq (IPoint, Ray->Initial);
  92.  
  93.     if (Point_In_Clip (&IPoint, Object->Clip))
  94.       {
  95.       push_entry(Depth1,IPoint,Object,Depth_Stack);
  96.       Intersection_Found = TRUE;
  97.       }
  98.  
  99.     if (Depth2 != Depth1)
  100.       {
  101.       VScale (IPoint, Ray->Direction, Depth2);
  102.       VAddEq (IPoint, Ray->Initial);
  103.  
  104.       if (Point_In_Clip (&IPoint, Object->Clip))
  105.     {
  106.     push_entry(Depth2,IPoint,Object,Depth_Stack);
  107.     Intersection_Found = TRUE;
  108.     }
  109.       }
  110.     }
  111.   return (Intersection_Found);
  112.   }
  113.  
  114. #ifdef DB_CODE
  115. /* Some things have been optimized. */
  116. /*****************************************************************************
  117.    The term VDot(Quadric->Mixed_Terms, Ray->Mixed_Initial_Initial)
  118.    is added to the cached constant CM_Constant. Thus 3 MUL and 3 ADD
  119.    are saved for primary rays.
  120.    The calculation of the coefficients of the quadratic equation
  121.    is rewritten to save 3 MUL.
  122.  *****************************************************************************/
  123. int Intersect_Quadric (Ray, Quadric, Depth1, Depth2)
  124. RAY *Ray;
  125. QUADRIC *Quadric;
  126. DBL *Depth1, *Depth2;
  127. {
  128.   register DBL Square_Term, Linear_Term, Constant_Term;
  129.   register DBL Determinant;
  130.  
  131.   Ray_Quadric_Tests++;
  132.  
  133.   if (!Ray->Quadric_Constants_Cached)
  134.     Make_Ray(Ray);
  135.  
  136.   if (Quadric->Non_Zero_Square_Term)
  137.   {
  138.     Square_Term = Quadric->Square_Terms.x * Ray->Direction_2.x +
  139.           Quadric->Square_Terms.y * Ray->Direction_2.y +
  140.           Quadric->Square_Terms.z * Ray->Direction_2.z +
  141.           Quadric->Mixed_Terms.x * Ray->Mixed_Dir_Dir.x +
  142.           Quadric->Mixed_Terms.y * Ray->Mixed_Dir_Dir.y +
  143.           Quadric->Mixed_Terms.z * Ray->Mixed_Dir_Dir.z;
  144.   }
  145.   else
  146.   {
  147.     Square_Term = 0.0;
  148.   }
  149.  
  150.   Linear_Term = Quadric->Square_Terms.x * Ray->Initial_Direction.x +
  151.         Quadric->Square_Terms.y * Ray->Initial_Direction.y +
  152.         Quadric->Square_Terms.z * Ray->Initial_Direction.z +
  153.         0.5 * (Quadric->Terms.x * Ray->Direction.x +
  154.                Quadric->Terms.y * Ray->Direction.y +
  155.                Quadric->Terms.z * Ray->Direction.z +
  156.                Quadric->Mixed_Terms.x * Ray->Mixed_Init_Dir.x +
  157.                Quadric->Mixed_Terms.y * Ray->Mixed_Init_Dir.y +
  158.                Quadric->Mixed_Terms.z * Ray->Mixed_Init_Dir.z);
  159.  
  160.   if (Ray == CM_Ray)
  161.   {
  162.     if (!Quadric->Constant_Cached)
  163.     {
  164.       Constant_Term = Quadric->Square_Terms.x * Ray->Initial_2.x +
  165.               Quadric->Square_Terms.y * Ray->Initial_2.y +
  166.               Quadric->Square_Terms.z * Ray->Initial_2.z +
  167.               Quadric->Terms.x * Ray->Initial.x +
  168.               Quadric->Terms.y * Ray->Initial.y +
  169.               Quadric->Terms.z * Ray->Initial.z +
  170.               Quadric->Mixed_Terms.x * Ray->Mixed_Initial_Initial.x +
  171.               Quadric->Mixed_Terms.y * Ray->Mixed_Initial_Initial.y +
  172.               Quadric->Mixed_Terms.z * Ray->Mixed_Initial_Initial.z +
  173.               Quadric->Constant;
  174.       Quadric->CM_Constant = Constant_Term;
  175.       Quadric->Constant_Cached = TRUE;
  176.     }
  177.     else
  178.     {
  179.       Constant_Term = Quadric->CM_Constant;
  180.     }
  181.   }
  182.   else
  183.   {
  184.     Constant_Term = Quadric->Square_Terms.x * Ray->Initial_2.x +
  185.             Quadric->Square_Terms.y * Ray->Initial_2.y +
  186.             Quadric->Square_Terms.z * Ray->Initial_2.z +
  187.             Quadric->Terms.x * Ray->Initial.x +
  188.             Quadric->Terms.y * Ray->Initial.y +
  189.             Quadric->Terms.z * Ray->Initial.z +
  190.             Quadric->Mixed_Terms.x * Ray->Mixed_Initial_Initial.x +
  191.             Quadric->Mixed_Terms.y * Ray->Mixed_Initial_Initial.y +
  192.             Quadric->Mixed_Terms.z * Ray->Mixed_Initial_Initial.z +
  193.             Quadric->Constant;
  194.   }
  195.  
  196.   if (Square_Term != 0.0)
  197.   {
  198.     /* The equation is quadratic - find its roots */
  199.  
  200.     Determinant = Linear_Term * Linear_Term - Square_Term * Constant_Term;
  201.  
  202.     if (Determinant < 0.0)
  203.       return (FALSE);
  204.  
  205.     Determinant = sqrt (Determinant);
  206.  
  207.     *Depth1 = (-Linear_Term + Determinant) / Square_Term;
  208.     *Depth2 = (-Linear_Term - Determinant) / Square_Term;
  209.   }
  210.   else
  211.   {
  212.     /* There are no quadratic terms.  Solve the linear equation instead. */
  213.     if (Linear_Term == 0.0)
  214.       return (FALSE);
  215.  
  216.     *Depth1 = -2.0 * Constant_Term / Linear_Term;
  217.     *Depth2 = *Depth1;
  218.   }
  219.  
  220.   if ((*Depth1 < Small_Tolerance) || (*Depth1 > Max_Distance))
  221.     if ((*Depth2 < Small_Tolerance) || (*Depth2 > Max_Distance))
  222.       return (FALSE);
  223.     else
  224.       *Depth1 = *Depth2;
  225.   else
  226.     if ((*Depth2 < Small_Tolerance) || (*Depth2 > Max_Distance))
  227.       *Depth2 = *Depth1;
  228.  
  229.   Ray_Quadric_Tests_Succeeded++;
  230.   return (TRUE);
  231. }
  232. #else
  233. int Intersect_Quadric (Ray, Quadric, Depth1, Depth2)
  234. RAY *Ray;
  235. QUADRIC *Quadric;
  236. DBL *Depth1, *Depth2;
  237.   {
  238.   register DBL Square_Term, Linear_Term, Constant_Term, Temp_Term;
  239.   register DBL Determinant, Determinant_2, A2, BMinus;
  240.  
  241.   Ray_Quadric_Tests++;
  242.   if (!Ray->Quadric_Constants_Cached)
  243.     Make_Ray(Ray);
  244.  
  245.   if (Quadric->Non_Zero_Square_Term)
  246.     {
  247.     VDot (Square_Term, Quadric->Square_Terms, Ray->Direction_2);
  248.     VDot (Temp_Term, Quadric->Mixed_Terms, Ray->Mixed_Dir_Dir);
  249.     Square_Term += Temp_Term;
  250.     }
  251.   else
  252.     Square_Term = 0.0;
  253.  
  254.   VDot (Linear_Term, Quadric->Square_Terms, Ray->Initial_Direction);
  255.   Linear_Term *= 2.0;
  256.   VDot (Temp_Term, Quadric->Terms, Ray->Direction);
  257.   Linear_Term += Temp_Term;
  258.   VDot (Temp_Term, Quadric->Mixed_Terms, Ray->Mixed_Init_Dir);
  259.   Linear_Term += Temp_Term;
  260.  
  261.   if (Ray == CM_Ray)
  262.     if (!Quadric->Constant_Cached)
  263.       {
  264.       VDot (Constant_Term, Quadric->Square_Terms, Ray->Initial_2);
  265.       VDot (Temp_Term, Quadric->Terms, Ray->Initial);
  266.       Constant_Term +=  Temp_Term + Quadric->Constant;
  267.       Quadric->CM_Constant = Constant_Term;
  268.       Quadric->Constant_Cached = TRUE;
  269.       }
  270.     else
  271.       Constant_Term = Quadric->CM_Constant;
  272.   else
  273.     {
  274.     VDot (Constant_Term, Quadric->Square_Terms, Ray->Initial_2);
  275.     VDot (Temp_Term, Quadric->Terms, Ray->Initial);
  276.     Constant_Term += Temp_Term + Quadric->Constant;
  277.     }
  278.  
  279.   VDot (Temp_Term, Quadric->Mixed_Terms, 
  280.     Ray->Mixed_Initial_Initial);
  281.   Constant_Term += Temp_Term;
  282.  
  283.   if (Square_Term != 0.0)
  284.     {
  285.     /* The equation is quadratic - find its roots */
  286.  
  287.     Determinant_2 = Linear_Term * Linear_Term - 4.0 * Square_Term * Constant_Term;
  288.  
  289.     if (Determinant_2 < 0.0)
  290.       return (FALSE);
  291.  
  292.     Determinant = sqrt (Determinant_2);
  293.     A2 = Square_Term * 2.0;
  294.     BMinus = Linear_Term * -1.0;
  295.  
  296.     *Depth1 = (BMinus + Determinant) / A2;
  297.     *Depth2 = (BMinus - Determinant) / A2;
  298.     }
  299.   else
  300.     {
  301.     /* There are no quadratic terms.  Solve the linear equation instead. */
  302.     if (Linear_Term == 0.0)
  303.       return (FALSE);
  304.  
  305.     *Depth1 = Constant_Term * -1.0 / Linear_Term;
  306.     *Depth2 = *Depth1;
  307.     }
  308.  
  309.   if ((*Depth1 < Small_Tolerance) || (*Depth1 > Max_Distance))
  310.     if ((*Depth2 < Small_Tolerance) || (*Depth2 > Max_Distance))
  311.       return (FALSE);
  312.     else
  313.       *Depth1 = *Depth2;
  314.   else
  315.     if ((*Depth2 < Small_Tolerance) || (*Depth2 > Max_Distance))
  316.       *Depth2 = *Depth1;
  317.  
  318.   Ray_Quadric_Tests_Succeeded++;
  319.   return (TRUE);
  320.   }
  321. #endif
  322.  
  323. #ifdef DB_CODE
  324. /* Some things have been optimized. */
  325. /*****************************************************************************
  326.    Rewriting saves 6 MUL.
  327.  *****************************************************************************/
  328. int Inside_Quadric (IPoint, Object)
  329. VECTOR *IPoint;
  330. OBJECT *Object;
  331. {
  332.   QUADRIC *Quadric = (QUADRIC *) Object;
  333.   register DBL Result;
  334.  
  335.   Result =
  336.  
  337.     IPoint->x * (Quadric->Square_Terms.x * IPoint->x +
  338.          Quadric->Mixed_Terms.x * IPoint->y +
  339.          Quadric->Terms.x) +
  340.  
  341.     IPoint->y * (Quadric->Square_Terms.y * IPoint->y +
  342.          Quadric->Mixed_Terms.z * IPoint->z +
  343.          Quadric->Terms.y) +
  344.  
  345.     IPoint->z * (Quadric->Square_Terms.z * IPoint->z +
  346.          Quadric->Mixed_Terms.y * IPoint->x +
  347.          Quadric->Terms.z) +
  348.  
  349.     Quadric->Constant;
  350.  
  351.   return (Result < Small_Tolerance);
  352. }
  353. #else
  354. int Inside_Quadric (IPoint, Object)
  355. VECTOR *IPoint;
  356. OBJECT *Object;
  357.   {
  358.   QUADRIC *Quadric = (QUADRIC *) Object;
  359.   VECTOR New_Point;
  360.   register DBL Result, Linear_Term, Square_Term;
  361.  
  362.   VDot (Linear_Term, *IPoint, Quadric->Terms);
  363.   Result = Linear_Term + Quadric->Constant;
  364.   VSquareTerms (New_Point, *IPoint);
  365.   VDot (Square_Term, New_Point, Quadric->Square_Terms);
  366.   Result += Square_Term;
  367.   Result += Quadric->Mixed_Terms.x * (IPoint->x) * (IPoint->y)
  368.     + Quadric->Mixed_Terms.y * (IPoint->x) * (IPoint->z)
  369.       + Quadric->Mixed_Terms.z * (IPoint->y) * (IPoint->z);
  370.  
  371.   if (Result < Small_Tolerance)
  372.     return (TRUE);
  373.  
  374.   return (FALSE);
  375.   }
  376. #endif
  377.  
  378. #ifdef DB_CODE
  379. /* Some things have been optimized. */
  380. /*****************************************************************************
  381.    Rewriting saves some memory transfers.
  382.    Storing of 2.0 * Square_Terms would save 3 MUL.
  383.  *****************************************************************************/
  384. void Quadric_Normal (Result, Object, IPoint)
  385. VECTOR *Result, *IPoint;
  386. OBJECT *Object;
  387. {
  388.   QUADRIC *Quadric = (QUADRIC *) Object;
  389.   DBL Len;
  390.  
  391.   Result->x = 2.0 * Quadric->Square_Terms.x * IPoint->x +
  392.           Quadric->Mixed_Terms.x * IPoint->y +
  393.           Quadric->Mixed_Terms.y * IPoint->z +
  394.           Quadric->Terms.x;
  395.  
  396.   Result->y = 2.0 * Quadric->Square_Terms.y * IPoint->y +
  397.           Quadric->Mixed_Terms.x * IPoint->x +
  398.           Quadric->Mixed_Terms.z * IPoint->z +
  399.           Quadric->Terms.y;
  400.  
  401.   Result->z = 2.0 * Quadric->Square_Terms.z * IPoint->z +
  402.           Quadric->Mixed_Terms.y * IPoint->x +
  403.           Quadric->Mixed_Terms.z * IPoint->y +
  404.           Quadric->Terms.z;
  405.  
  406.   Len = sqrt(Result->x * Result->x + Result->y * Result->y + Result->z * Result->z);
  407.  
  408.   if (Len == 0.0)
  409.   {
  410.     /* The normal is not defined at this point of the surface. */
  411.     /* Set it to any arbitrary direction. */
  412.     Result->x = 1.0;
  413.     Result->y = 0.0;
  414.     Result->z = 0.0;
  415.   }
  416.   else
  417.   {
  418.     Result->x /= Len;        /* normalize the normal */
  419.     Result->y /= Len;
  420.     Result->z /= Len;
  421.   }
  422. }
  423. #else
  424. void Quadric_Normal (Result, Object, IPoint)
  425. VECTOR *Result, *IPoint;
  426. OBJECT *Object;
  427.   {
  428.   QUADRIC *Intersection_Quadric = (QUADRIC *) Object;
  429.   VECTOR Derivative_Linear;
  430.   DBL Len;
  431.  
  432.   VScale (Derivative_Linear, Intersection_Quadric->Square_Terms, 2.0);
  433.   VEvaluate (*Result, Derivative_Linear, *IPoint);
  434.   VAdd (*Result, *Result, Intersection_Quadric->Terms);
  435.  
  436.   Result->x +=
  437.   Intersection_Quadric->Mixed_Terms.x * IPoint->y +
  438.   Intersection_Quadric->Mixed_Terms.y * IPoint->z;
  439.  
  440.  
  441.   Result->y +=
  442.   Intersection_Quadric->Mixed_Terms.x * IPoint->x +
  443.   Intersection_Quadric->Mixed_Terms.z * IPoint->z;
  444.  
  445.   Result->z +=
  446.   Intersection_Quadric->Mixed_Terms.y * IPoint->x +
  447.   Intersection_Quadric->Mixed_Terms.z * IPoint->y;
  448.  
  449.   Len = Result->x * Result->x + Result->y * Result->y + Result->z * Result->z;
  450.   Len = sqrt(Len);
  451.   if (Len == 0.0) 
  452.     {
  453.     /* The normal is not defined at this point of the surface.  Set it
  454.          to any arbitrary direction. */
  455.     Result->x = 1.0;
  456.     Result->y = 0.0;
  457.     Result->z = 0.0;
  458.     }
  459.   else
  460.     {
  461.     Result->x /= Len;        /* normalize the normal */
  462.     Result->y /= Len;
  463.     Result->z /= Len;
  464.     }
  465.   }
  466. #endif
  467.  
  468.   void Transform_Quadric (Object, Trans)
  469.     OBJECT *Object;
  470. TRANSFORM *Trans;
  471.   {
  472.   QUADRIC *Quadric=(QUADRIC *)Object;
  473.   MATRIX Quadric_Matrix, Transform_Transposed;
  474.  
  475.   Quadric_To_Matrix (Quadric, (MATRIX *) &Quadric_Matrix[0][0]);
  476.   MTimes ((MATRIX *) &Quadric_Matrix[0][0], (MATRIX *) &(Trans->inverse[0][0]), (MATRIX *) &Quadric_Matrix[0][0]);
  477.   MTranspose ((MATRIX *) &Transform_Transposed[0][0], (MATRIX *) &(Trans->inverse[0][0]));
  478.   MTimes ((MATRIX *) &Quadric_Matrix[0][0], (MATRIX *) &Quadric_Matrix[0][0], (MATRIX *) &Transform_Transposed[0][0]);
  479.   Matrix_To_Quadric ((MATRIX *) &Quadric_Matrix[0][0], Quadric);
  480. #ifdef DB_CODE
  481.   /* this has been missing. */
  482.   recompute_bbox(&Object->Bounds, Trans);
  483. #endif
  484.   }
  485.  
  486. void Quadric_To_Matrix (Quadric, Matrix)
  487. QUADRIC *Quadric;
  488. MATRIX *Matrix;
  489.   {
  490.   MZero (Matrix);
  491.   (*Matrix)[0][0] = Quadric->Square_Terms.x;
  492.   (*Matrix)[1][1] = Quadric->Square_Terms.y;
  493.   (*Matrix)[2][2] = Quadric->Square_Terms.z;
  494.   (*Matrix)[0][1] = Quadric->Mixed_Terms.x;
  495.   (*Matrix)[0][2] = Quadric->Mixed_Terms.y;
  496.   (*Matrix)[0][3] = Quadric->Terms.x;
  497.   (*Matrix)[1][2] = Quadric->Mixed_Terms.z;
  498.   (*Matrix)[1][3] = Quadric->Terms.y;
  499.   (*Matrix)[2][3] = Quadric->Terms.z;
  500.   (*Matrix)[3][3] = Quadric->Constant;
  501.   }
  502.  
  503. void Matrix_To_Quadric (Matrix, Quadric)
  504. MATRIX *Matrix;
  505. QUADRIC *Quadric;
  506.   {
  507.   Quadric->Square_Terms.x = (*Matrix)[0][0];
  508.   Quadric->Square_Terms.y = (*Matrix)[1][1];
  509.   Quadric->Square_Terms.z = (*Matrix)[2][2];
  510.   Quadric->Mixed_Terms.x = (*Matrix)[0][1] + (*Matrix)[1][0];
  511.   Quadric->Mixed_Terms.y = (*Matrix)[0][2] + (*Matrix)[2][0];
  512.   Quadric->Terms.x = (*Matrix)[0][3] + (*Matrix)[3][0];
  513.   Quadric->Mixed_Terms.z = (*Matrix)[1][2] + (*Matrix)[2][1];
  514.   Quadric->Terms.y = (*Matrix)[1][3] + (*Matrix)[3][1];
  515.   Quadric->Terms.z = (*Matrix)[2][3] + (*Matrix)[3][2];
  516.   Quadric->Constant = (*Matrix)[3][3];
  517.   }
  518.  
  519. void Translate_Quadric (Object, Vector)
  520. OBJECT *Object;
  521. VECTOR *Vector;
  522.   {
  523.   TRANSFORM Trans;
  524.  
  525.   Compute_Translation_Transform (&Trans, Vector);
  526.   Transform_Quadric (Object, &Trans);
  527.  
  528.   }
  529.  
  530. void Rotate_Quadric (Object, Vector)
  531. OBJECT *Object;
  532. VECTOR *Vector;
  533.   {
  534.   TRANSFORM Trans;
  535.  
  536.   Compute_Rotation_Transform (&Trans, Vector);
  537.   Transform_Quadric (Object, &Trans);
  538.   }
  539.  
  540. void Scale_Quadric (Object, Vector)
  541. OBJECT *Object;
  542. VECTOR *Vector;
  543.   {
  544.   TRANSFORM Trans;
  545.  
  546.   Compute_Scaling_Transform (&Trans, Vector);
  547.   Transform_Quadric (Object, &Trans);
  548.   }
  549.  
  550. void Invert_Quadric (Object)
  551. OBJECT *Object;
  552.   {
  553.   QUADRIC *Quadric = (QUADRIC *) Object;
  554.  
  555.   VScaleEq (Quadric->Square_Terms, -1.0);
  556.   VScaleEq (Quadric->Mixed_Terms, -1.0);
  557.   VScaleEq (Quadric->Terms, -1.0);
  558.   Quadric->Constant *= -1.0;
  559. #ifdef DB_CODE
  560.   /* Necessary for new bounding box calculation of intersections. */
  561.   Quadric->Inverted ^= TRUE;
  562. #endif
  563.   }
  564.  
  565. QUADRIC *Create_Quadric()
  566.   {
  567.   QUADRIC *New;
  568.  
  569.   if ((New = (QUADRIC *) malloc (sizeof (QUADRIC))) == NULL)
  570.     MAError ("quadric");
  571.  
  572.   INIT_OBJECT_FIELDS(New, QUADRIC_OBJECT, &Quadric_Methods)
  573.     Make_Vector (&(New->Square_Terms), 1.0, 1.0, 1.0);
  574.   Make_Vector (&(New->Mixed_Terms), 0.0, 0.0, 0.0);
  575.   Make_Vector (&(New->Terms), 0.0, 0.0, 0.0);
  576.   New->Constant = 1.0;
  577.   New->CM_Constant = HUGE_VAL;
  578.   New->Constant_Cached = FALSE;
  579.   New->Non_Zero_Square_Term = FALSE;
  580. #ifdef DB_CODE
  581.   /* Necessary for new bounding box calculation of intersections. */
  582.   New->Inverted = FALSE;
  583. #endif
  584.  
  585.   return (New);
  586.   }
  587.  
  588. void *Copy_Quadric (Object)
  589. OBJECT *Object;
  590.   {
  591.   QUADRIC *New;
  592.  
  593.   New = Create_Quadric ();
  594.   *New = *((QUADRIC *) Object);
  595.  
  596.   return (New);
  597.   }
  598.  
  599. void Destroy_Quadric (Object)
  600. OBJECT *Object;
  601.   {
  602.   free (Object);
  603.   }
  604.